﻿#pragma once
namespace LK
{
    template<class T>WeakPtr<T>::WeakPtr() {}
    template<class T>WeakPtr<T>::WeakPtr(typename T::IObj const* ptr) :T() { PObject::pObject = (typename T::IObj*)ptr; if (ptr) { ptr->RefCount.Create(); T::RefCount = ptr->RefCount; } }
    template<class T>WeakPtr<T>::WeakPtr(const T& w) :T() { T::RefCount = w.RefCount; PObject::pObject = ((PObject&)w).pObject; }
    template<class T>WeakPtr<T>::WeakPtr(const WeakPtr&w) :T() { T::RefCount = w.RefCount; PObject::pObject = ((PObject&)w).pObject; }
    template<class T>template<class AnyT>WeakPtr<T>::WeakPtr(WeakPtr<AnyT>const& w, typename UseIf<IsBaseOf<T, AnyT>::V>::T*p) : T() { T::RefCount = w.PObject::RefCount; PObject::pObject = ((PObject&)w).PObject::pObject; }
    template<class T>WeakPtr<T>& WeakPtr<T>::operator=(const WeakPtr&w) { T::RefCount = w.RefCount; PObject::pObject = ((PObject&)w).pObject; return *this; }
    template<class T>void WeakPtr<T>::SetToNull() { PObject::RefCount.ChangeRef(NULL); PObject::pObject = NULL; }
    template<class T>void WeakPtr<T>::SetTo(typename T::IObj const*p) {if(p)PObject::RefCount=p->RefCount; PObject::pObject = (typename T::IObj)p; }
    template<class T>WeakPtr<T>::~WeakPtr() {T::RefCount.ChangeRef(NULL);}

	template<typename T>inline void PObject::template Ctor2(typename AddConst<typename AddLValueReference<T>::T>::T t)
	{
		PMObjects xr = PMObjects::MakeMObjectByTypeInfo(PType::Make<T>());
		union {
			typename AddPointer<T>::T pt;
			const void* p;
		};
		pt = (typename AddPointer<T>::T)&t;
		if (xr.GetInnerType().IsArray() || xr.GetInnerType().IsLValueReference() || xr.GetInnerType().IsFunction() != 0)//左值引用
			xr.GetInnerType().CopyConstruct(xr.GetDataPtr(), &p);
		else xr.GetInnerType().CopyConstruct(xr.GetDataPtr(), p);
		*this = xr;
	}
	template<typename T>inline PObject PObject::MakeObject(T t)
	{
		PObject obj;
		if (IsReference<T>::V)
		{
			obj = PMObjects::MakeMObjectByTypeInfo(PType::Make<T>());
			Convert<void, T>::WriteDataFrom(((PMObjects&)obj).GetDataPtr(), t);
		}
		else obj.Ctor<typename RemoveReference<T>::T>(t);
		return obj;
	}
	template <class T>T PMObjects::CastTo()const
	{
		if (IsNull())throw PException(L"无法转换空引用");
		if (PType::Make<T>() != GetInnerType())
			throw PTypesConvertErrorException(L"无法将类型 " + GetInnerType().GetName() + L"转换到类型 " + PType::Make<T>().GetName());
		return Convert<T, void>::FromDataPtr(GetDataPtr());
	}
	template <size_t size>MObject<size>::~MObject()
	{
		if (!innerDataType.IsNull())
		{
			if (ptmp)
				GetInnerType().DeconstructIgnoreReference(ptmp);
			else GetInnerType().Deconstruct(GetDataPtr());
		}
	}
	template<class T>inline T PObject::template CastTo1()const
	{
		if (IsNull())return T();
		T t;
		if (GetType() == PType::Make<T>())
			((PObject&)t).SetTo(PObject::GetPtr());
		else if (GetType() == PType::Make<PMObjects>())
		{
			PMObjects xx = (IMObject*)GetPtr();
			if (xx.IsNull())return T();
			t = xx.CastTo<T>();
		}
		else//查询派生关系
		{
			if (GetType().IsDerivedFrom(PType::Make<T>()))
				((PObject&)t).SetTo(GetPtr());
		}
		return t;
	}
	template<class T>inline T PObject::template CastTo2()const
	{
		if (IsNull())throw PPointerIsNullException();
		PMObjects x;
		if (GetType() == PType::Make<PMObjects>())
			x = (IMObject*)GetPtr();
		return x.CastTo<T>();
	}
	/**
	@brief 获取类型T的ID，该方法线程安全
	@note 类型T必须是最原生类型，否则将无法编译通过*/
	template<class T>inline long Type::GetId1()
	{
		typedef typename ::LK::VarArgsPack<void, bool, s8, s16, i32, s32, s64, u8, u16, ui32, u32, u64, float, double, long double, char, wchar_t> BaseTypes;
		if (ArgHasT<T, BaseTypes>::V)return ArgHasT<T, BaseTypes>::index + 1;
		static long index = 0;
		if (index != 0)return index;
		GetMutexRef().Lock();
		if (index == 0)
		{
			index = (long)GetLocalTypeId();
			if ((index_t)GetTypeCommonInfoRef().size() <= index)GetTypeCommonInfoRef().resize(index + 1);
		}
		GetTypeCommonInfoRef()[index].Name = typeid(typename UseT<IsGCHandle<T>::V, T,
#ifdef _CLR
			gcroot<typename UseT<IsGCHandle<T>::V, System::Object^, T>::T>
#else
			void
#endif
		>::T).name();
		typedef typename UseT<::LK::IsAbstract<T>::V || IsVoid<T>::V, T, int>::T LT;
#ifdef _CLR
		typedef typename UseT < ::LK::IsGCHandle<LT>::V, LT, gcroot<typename UseT<IsGCHandle<LT>::V, System::Object^, LT>::T> >::T TT;
#else
		typedef LT TT;
#endif
		//获取默认构造函数
		if (IsSame<TT, T>::V)
		{
			GetTypeCommonInfoRef()[index].size = sizeof(TT);
			GetTypeCommonInfoRef()[index].DeconstructMethod = &CommonTypeFunctionInfoStruct::template DefDeconstructMethod<TT>;
			GetTypeCommonInfoRef()[index].DefaultConstructMethod = &CommonTypeFunctionInfoStruct::template DefDefaultConstructMethod<TT>;
			GetTypeCommonInfoRef()[index].CopyConstructMethod = &CommonTypeFunctionInfoStruct::template DefCopyConstructMethod<TT>;
		}
		GetMutexRef().UnLock();
		return index;
	}
#ifdef SUPPORT_VARIADIC_TEMPLATES
	//抛出异常
	template<class T, class ...Args>void Throw(Args ...t) { throw T(t...); }
#else
	//抛出异常
#define TMPF(x) template<MF4_RepeatAsc_(class T,,0,x)>void Throw(MF2_Repeat_b(MF1_Tt,x)){throw T0(MF4_RepeatAsc_(t,,1,x));}
	MF3_RepeatAsc(TMPF, 0, 16);
#undef TMPF
#endif
	template<class _T, class _BT>struct __cast_tmp
	{
		static inline _T* _CastPointer(_BT const* p)
		{
			if (!p)return NULL;
			_T*pt = dynamic_cast<_T*>((_BT*)p);
			if (!pt)throw PPointerFailureException();
			return pt;
		}
	};
	template<class _T>struct __cast_tmp<_T, _T> { static inline _T* _CastPointer(_T const* p) { return (_T*)p; } };
	//动态转换基类指针到派生类，不做检查
	template<class T, class BT>T* CastPointer(BT const* p)
	{
		return __cast_tmp<T, BT>::_CastPointer(p);
	}
	//静态转换派生类指针到基类，不做检查
	template<class T>Object* StaticCastPointer(T const* p) { return (Object*)p; }
	//检查指针p，并在p为NULL时抛出空指针异常
	template<class T, class BT>T* CheckPointer(BT const* p)
	{
		if (p)return CastPointer<T, BT>(p);
		throw PPointerIsNullException();
	}

	//因为需要抛出异常，模板实现需要移至此处
	template<class T>T* Memory::New(size_t len)
	{
		try
		{
			return new T[len];
		}
		catch (std::bad_alloc)
		{
			throw POutOfMemoryException();
		}
	}
	template<class T>T* Memory::New(size_t Length, size_t* outSize)
	{
		size_t len = Memory::GetResize(Length*sizeof(T)) / sizeof(T);
		try
		{
			if (outSize)*outSize = len;
			return new T[len];
		}
		catch (std::bad_alloc)
		{
			throw POutOfMemoryException();
		}
	}

#ifdef LK_MEMORYBUFFERS_
	inline void* Memory::GetDefaultBuffer()
	{
		static MemoryBuffer*p;
		if (!p)
		{
			SpinMutex::GetDefaultRef().Lock();
			static MemoryBuffer m;
			p = &m;
			SpinMutex::GetDefaultRef().UnLock();
		}
		return p;
	}
#endif
	inline size_t Memory::GetBuffer(size_t count, unsigned char**p)
	{
		//每超过一定次数就清理一次缓存，减少缓存占用过多内存的问题
		static size_t i = 0;
		if (++i > 10000000) { i = 0;  ClearNotUsingBuffers(); }
#ifdef LK_MEMORYBUFFERS_
		return ((MemoryBuffer*)GetDefaultBuffer())->GetBuffer(count, p);
#else
		*p = new unsigned char[count];
		return 0;
#endif
	}
	inline void Memory::ReleaseBuffer(size_t mask, unsigned char*pointer)
	{
#ifdef LK_MEMORYBUFFERS_
		return ((MemoryBuffer*)GetDefaultBuffer())->ReleaseBuffer(mask, pointer);
#else
		delete[]pointer;
#endif
	}
	inline void Memory::ClearNotUsingBuffers()
	{
#ifdef LK_MEMORYBUFFERS_
		return ((MemoryBuffer*)GetDefaultBuffer())->ClearNotUsingBuffer();
#else

#endif
	}

	template <class T>PString PType::GetStringFromArgs()
	{
		typedef  typename UseT<IsSame<VarArgsPack<>, T>::V, T, VarArgsPack<void> >::T  TT;
		if (T::ArgCount == 0)return PString::GetEmpty();
		if (T::ArgCount == 1)return Make<typename ArgT<0, TT>::T>().GetName();
		return Make<typename ArgT<0, TT>::T>().GetName() + L"," + GetStringFromArgs<typename ArgRemoveAt<0, TT>::T>();
	}
#ifdef LK_FUNCTIONAL_
#ifdef SUPPORT_VARIADIC_TEMPLATES
	template<class ReturnType, class ...ArgumentsType>void  Functional::PFunObj<ReturnType(ArgumentsType...) >::AddTypeInfo()
	{
#ifdef LK_REFLECTION_
		//引用反射命名空间
		using namespace Reflection;
		//获取类库的引用
		PTypeLibrary lib = GetGlobleLibrary();
		//获取类库中的全局命名空间
		PNamespaceNode globle = lib.GetGlobleNamespaceRef();
		//添加LK命名空间
		PNamespaceNode space = globle.FindOrAddNamespace(L"LK");
		//在LK命名空间中添加PException类型
		PTypeNode n = space.FindOrAddTypeNode(L"PFunObj<" + PString(PType::Make<PFunObj<ReturnType(ArgumentsType...) > >().GetID()) + L">", PType::Make<PFunObj<ReturnType(ArgumentsType...) > >());
		//设置继承
		n.AddBaseType(PType::Make<PFunObjs>());
#endif
	}
	template<class FunctionType, class ReturnType, class ...ArgumentsType>
	void Functional::PFunObject<FunctionType, VarArgsPack<ReturnType, void, ArgumentsType...>, true>::AddTypeInfo()
	{
#ifdef LK_REFLECTION_
		//引用反射命名空间
		using namespace Reflection;
		//获取类库的引用
		PTypeLibrary lib = GetGlobleLibrary();
		//获取类库中的全局命名空间
		PNamespaceNode globle = lib.GetGlobleNamespaceRef();
		//添加LK命名空间
		PNamespaceNode space = globle.FindOrAddNamespace(L"LK");
		//在LK命名空间中添加PException类型
		PTypeNode n = space.FindOrAddTypeNode(L"PFunObject<" + PString(PType::Make<PFunObject<FunctionType, VarArgsPack<ReturnType, void, ArgumentsType...>, true> >().GetID()) + L">", PType::Make<PFunObject<FunctionType, VarArgsPack<ReturnType, void, ArgumentsType...>, true> >());
		//设置继承
		n.AddBaseType(PType::Make<PFunObj<ReturnType(ArgumentsType...) > >());
#endif
	}
	template<class FunctionType, class ReturnType, class CType, class ...ArgumentsType>
	void Functional::PFunObject<FunctionType, VarArgsPack<ReturnType, CType, ArgumentsType...>, true>::AddTypeInfo()
	{
#ifdef LK_REFLECTION_
		//引用反射命名空间
		using namespace Reflection;
		//获取类库的引用
		PTypeLibrary lib = GetGlobleLibrary();
		//获取类库中的全局命名空间
		PNamespaceNode globle = lib.GetGlobleNamespaceRef();
		//添加LK命名空间
		PNamespaceNode space = globle.FindOrAddNamespace(L"LK");
		//在LK命名空间中添加PException类型
		PTypeNode n = space.FindOrAddTypeNode(L"PFunObject<" + PString(PType::Make<PFunObject<FunctionType, VarArgsPack<ReturnType, CType, ArgumentsType...>, true> >().GetID()) + L">", PType::Make<PFunObject<FunctionType, VarArgsPack<ReturnType, CType, ArgumentsType...>, true> >());
		//设置继承
		n.AddBaseType(PType::Make<PFunObj<ReturnType(ArgumentsType...) > >());
#endif
}
#else
#define TMPCT(x) ,class T##x
#define TMPT(x) ,T##x
#ifdef LK_REFLECTION_
#define TMPF_1(x)\
		using namespace Reflection;\
		PTypeLibrary lib = GetGlobleLibrary();\
		PNamespaceNode globle = lib.GetGlobleNamespaceRef();\
		PNamespaceNode space = globle.FindOrAddNamespace(L"LK");\
		PTypeNode n = space.FindOrAddTypeNode(L"PFunObj<"\
		+ PString(PType::Make<PFunObj<ReturnType( MF4_RepeatAsc_(T,,2,x)) > >().GetID()) + L">", PType::Make<PFunObj<ReturnType (MF4_RepeatAsc_(T,,2,x)) > >());\
		n.AddBaseType(PType::Make<PFunObjs>());
#define TMPF_2(x)\
		using namespace Reflection;\
		PTypeLibrary lib = GetGlobleLibrary();\
		PNamespaceNode globle = lib.GetGlobleNamespaceRef();\
		PNamespaceNode space = globle.FindOrAddNamespace(L"LK");\
		PTypeNode n = space.FindOrAddTypeNode(L"PFunObject<"\
		+ PString(PType::Make<PFunObject<FunctionType, VarArgsPack<ReturnType, void MF3_RepeatAsc(TMPT,2,x)>, true> >().GetID()) + L">", PType::Make<PFunObject<FunctionType, VarArgsPack<ReturnType, void MF3_RepeatAsc(TMPT,2,x)>, true> >());\
		n.AddBaseType(PType::Make<PFunObj<ReturnType (MF4_RepeatAsc_(T,,2,x)) > >());
#define TMPF_3(x)\
		using namespace Reflection;\
		PTypeLibrary lib = GetGlobleLibrary();\
		PNamespaceNode globle = lib.GetGlobleNamespaceRef();\
		PNamespaceNode space = globle.FindOrAddNamespace(L"LK");\
		PTypeNode n = space.FindOrAddTypeNode(L"PFunObject<"\
		+ PString(PType::Make<PFunObject<FunctionType, VarArgsPack<ReturnType, CType MF3_RepeatAsc(TMPT,2,x)>, true> >().GetID()) + L">", PType::Make<PFunObject<FunctionType, VarArgsPack<ReturnType, CType MF3_RepeatAsc(TMPT,2,x)>, true> >());\
		n.AddBaseType(PType::Make<PFunObj<ReturnType (MF4_RepeatAsc_(T,,2,x)) > >());
#else
#define TMPF_1(x)
#define TMPF_2(x)
#define TMPF_3(x)
#endif
#define TMPF(x)\
	template<class ReturnType MF3_RepeatAsc(TMPCT,2,x)>void  Functional::PFunObj<ReturnType (MF4_RepeatAsc_(T,,2,x)) >::AddTypeInfo(){TMPF_1(x)}\
	template<class FunctionType, class ReturnType MF3_RepeatAsc(TMPCT,2,x)>void Functional::PFunObject<FunctionType, VarArgsPack<ReturnType, void MF3_RepeatAsc(TMPT,2,x)>, true>::AddTypeInfo(){TMPF_2(x)}\
	template<class FunctionType, class ReturnType,class CType MF3_RepeatAsc(TMPCT,2,x)>void Functional::PFunObject<FunctionType, VarArgsPack<ReturnType, CType MF3_RepeatAsc(TMPT,2,x)>, true>::AddTypeInfo(){TMPF_3(x)}
	MF2_Repeatb(TMPF, 30)
#undef TMPF_1
#undef TMPF_2
#undef TMPF_3
#undef TMPF
#undef TMPCT
#undef TMPT
#endif
#ifdef LK_FUNCTIONAL_ACTION_
#ifdef SUPPORT_VARIADIC_TEMPLATES
		template<class T0, class ...Args>Functional::PActions::PActions(PDelegates d, T0 t0, Args ... t)
		:PFunObject<WeakPtr<PActions>, VarArgsPack<void, void>, true>(new IActions())
	{
		if (d.IsNull())throw PInvalidArgumentException(L"指定的委托为空");
		GetPtr()->delegates = d;
		GetPtr()->args = new Collection::DefaultArray<PObject>();
		AddArgs<T0, Args...>(t0, t...);
	}
	template<class T0, class ...Args>Functional::PActions Functional::PActions::AddArgs(T0 t0, Args ... t)
	{
		GetPtr()->args.Append(PObject::MakeObject<T0>(t0));
		return AddArgs<Args...>(t...);
	}
#else
#define TMPCT(x) ,class T##x
#define TMPTt(x) ,T##x t##x
#define TMPAPPENDt(x) GetPtr()->args.Append(PObject::MakeObject<T##x>(t##x));
#define TMPF(x)\
		template<class T1 MF3_RepeatAsc(TMPCT,2,x)>Functional::PActions::PActions(PDelegates d MF3_RepeatAsc(TMPTt,1,x))\
		:PFunObject<WeakPtr<PActions>, VarArgsPack<void, void>, true>(new IActions()){\
			if (d.IsNull())throw PInvalidArgumentException(L"指定的委托为空");\
			GetPtr()->delegates = d;\
			GetPtr()->args = new Collection::DefaultArray<PObject>();\
			AddArgs<MF4_RepeatAsc_(T,,1,x)>(MF4_RepeatAsc_(t,,1,x));\
		}\
		template<class T0 MF3_RepeatAsc(TMPCT,1,x)> Functional::PActions Functional::PActions::AddArgs(PString const&functionName MF3_RepeatAsc(TMPTt,0,x))const\
		{\
			MF3_RepeatAsc(TMPAPPENDt,0,x)\
			return*this;\
		}
		MF2_Repeatb(TMPF, 31)
#undef TMPF
#undef TMPAPPENDt
#undef TMPCT
#undef TMPT
#endif
		template<class T0>Functional::PActions Functional::PActions::AddArgs(T0 t0)
	{
		GetPtr()->args.Append(PObject::MakeObject<T0>(t0));
		return *this;
	}
#endif
#endif
	template<class T>void Collection::PArray<T>::AddTypeInfo()
	{
#ifdef LK_REFLECTION_
		//引用反射命名空间
		using namespace Reflection;
		//获取类库的引用
		PTypeLibrary lib = GetGlobleLibrary();
		//获取类库中的全局命名空间
		PNamespaceNode globle = lib.GetGlobleNamespaceRef();
		//添加LK命名空间
		PNamespaceNode space = globle.FindOrAddNamespace(L"LK");
		space = space.FindOrAddNamespace(L"Collection");
		//在LK命名空间中添加PArray<T>类型
		PTypeNode n = space.FindOrAddTypeNode(L"PArray<" + PType::Make<T>().ToString() + L">", PType::Make<PArray<T> >());
		//设置继承关系
		n.AddBaseType(PType::Make<PObject>());
#endif
	}
	template<class T>void Collection::PDefaultArray<T>::AddTypeInfo()
	{
#ifdef LK_REFLECTION_
		//引用反射命名空间
		using namespace Reflection;
		//获取类库的引用
		PTypeLibrary lib = GetGlobleLibrary();
		//获取类库中的全局命名空间
		PNamespaceNode globle = lib.GetGlobleNamespaceRef();
		//添加LK命名空间
		PNamespaceNode space = globle.FindOrAddNamespace(L"LK");
		space = space.FindOrAddNamespace(L"Collection");
		//在LK命名空间中添加PDefaultArray<T>类型
		PTypeNode n = space.FindOrAddTypeNode(L"PDefaultArray<" + PType::Make<T>().ToString() + L">", PType::Make<PDefaultArray<T> >());
		//设置继承
		n.AddBaseType(PType::Make<PArray<T> >());
#endif
	}
	template<class T>void Collection::PVector<T>::AddTypeInfo()
	{
#ifdef LK_REFLECTION_
		//引用反射命名空间
		using namespace Reflection;
		//获取类库的引用
		PTypeLibrary lib = GetGlobleLibrary();
		//获取类库中的全局命名空间
		PNamespaceNode globle = lib.GetGlobleNamespaceRef();
		//添加LK命名空间
		PNamespaceNode space = globle.FindOrAddNamespace(L"LK");
		space = space.FindOrAddNamespace(L"Collection");
		//在LK命名空间中添加PVector<T>类型
		PTypeNode n = space.FindOrAddTypeNode(L"PVector<" + PType::Make<T>().ToString() + L">", PType::Make<PVector<T> >());
		//设置继承
		n.AddBaseType(PType::Make<PVector<T> >());
#endif
	}

}
